use strict;

use Getopt::Long;

# defaults
my $retry_num = 5;
my $size_from = 1;
my $size_to   = 1024*16;
my $step      = 2;
my $mess_num  = 100000;

&main();


sub main()
{
    &init_vars();

    my @results;
    for ( my $mess_size = $size_from; $mess_size < $size_to; $mess_size += $step )
    {
        push @results, &iter( $mess_size, $mess_num);
    }
    print scalar @results;

    open( my $fh, ">", "stats/1a") or die "cannot open: $!";
    print $fh "mess_size MPI_Send MPI_Ssend MPI_Bsend\n";
    foreach my $res ( @results)
    {
        $| = 1;
        print $fh ($res->{mess_size} . " " .  $res->{send} . " " .  $res->{ssend} . " " . $res->{bsend} . "\n"); 
    }
    close $fh;
    return 0; 
}

sub init_vars
{
    my $result = &GetOptions (
        "from=i"        => \$size_from, 
        "to=i"          => \$size_to,
        "step=i"        => \$step,
        "mess_num=i"    => \$mess_num,
        "retry_num=i"   => \$retry_num,
    );
}

sub cpu_wait
{
    my $time = 3;
    while (1)
    {
        my $cpu = `cat /proc/loadavg`;
        if ( $cpu =~ /^(\d*\.\d*)/)
        {
            if ( $1 < 6.0)
            {
                return;
            } 
        }
        print "Waiting $time. Cpu load $1\n";
        sleep $time;
    }
}

sub iter()
{
    my $mess_size = shift;
    my $mess_num  = shift;
    my %res;
   
    $res{mess_size} = $mess_size; 
    $res{send} = 0;
    $res{ssend} = 0;
    $res{bsed}  = 0;

    for ( my $i = 0; $i < $retry_num; $i++)
    {
        &cpu_wait();
        my $res = `mpiexec -n 2 ./bin/1a $mess_size $mess_num 2>err`;
        print $mess_size . "\t" . $res . "\n";
        if ( $res =~ /Result:\s(\d*)\s(\d*)\s(\d*)/)
        {
            $res{send}  = ( $res{send}  * $i + $1) / ( $i + 1);
            $res{ssend} = ( $res{ssend} * $i + $1) / ( $i + 1);
            $res{bsend} = ( $res{bsend} * $i + $1) / ( $i + 1);
        }
    }
    $res{send}  /= $mess_num;
    $res{ssend} /= $mess_num;
    $res{bsend} /= $mess_num;

    return \%res;
}


